﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Text;
using System.Web;
using System.Xml.Linq;
//
using PerceptiveMCAPI.Types;
//
namespace PerceptiveMCAPI
{
	public class apiSerial
	{
		// ------------------------------------------
		internal static string ProcessRequest(
			Api_BaseInput input, Dictionary<string, string> parameters,
			out string request
			)
		{
			// ----------- setup base request
			string outputType = input.api_OutputType.ToString().ToLower();
			string baseURL = string.Format( "{0}/?output={1}", input.SubmitUrl, outputType );

			StringBuilder sb = new StringBuilder( baseURL );
			sb.Append( "&method=" + input.api_Method );
			// ===============================================================
			HttpWebRequest wRequest;
			// ----------- build request data based on method type
			// -- GET --
			string GET_request = "";
			if ( input.api_MethodType == EnumValues.MethodType.GET )
			{
				foreach ( KeyValuePair<string, string> parm in parameters )
				{
					if ( input.api_EncodeRequest )
						sb.Append( string.Format( "&{0}={1}", parm.Key, HttpUtility.UrlEncode( parm.Value ) ) );
					else
						sb.Append( string.Format( "&{0}={1}", parm.Key, parm.Value ) );
				}
				//
				GET_request = sb.ToString();
				wRequest = WebRequest.Create( GET_request ) as HttpWebRequest;
				wRequest.Method = "GET";
				request = GET_request;
			}
			else
			{
				// -- POST --
				string POST_request = sb.ToString();
				request = POST_request + " <|| POST:: " + apiHelper.DictionaryToString( parameters ) + " ||>";
				//
				wRequest = WebRequest.Create( POST_request ) as HttpWebRequest;
				wRequest.Method = "POST";
				wRequest.ContentType = "application/x-www-form-urlencoded";
				//
				int index = 0;
				string[] encodedParameters = new string[parameters.Count];
				foreach ( KeyValuePair<string, string> parameter in parameters )
				{
					encodedParameters[index++] = HttpUtility.UrlEncode( parameter.Key ) + "=" + HttpUtility.UrlEncode( parameter.Value );
				}
				ASCIIEncoding encoding = new ASCIIEncoding();
				byte[] requestData = encoding.GetBytes( string.Join( "&", encodedParameters ) );
				wRequest.ContentLength = requestData.Length;
				//
				Stream stream = wRequest.GetRequestStream();
				stream.Write( requestData, 0, requestData.Length );
				stream.Close();
			}
			// ===============================================================
			// same for both...
			// ------------------------------- Get the response
			//
			HttpWebResponse wResponse = wRequest.GetResponse() as HttpWebResponse;

			StreamReader reader = new StreamReader( wResponse.GetResponseStream() );
			string APIResponse = reader.ReadToEnd();

			wResponse.Close();
			reader.Close();

			APIResponse = APIResponse.Replace( ">\n<", "><" );  // get rid of the new lines
			return APIResponse;
		}

		#region ------------------------------------------------------------ common use

		// ---------------------------------------------------------------------------- FormatMemberMergeVars
		internal static Dictionary<string, string> FormatMemberMergeVars( Dictionary<string, object> merge_vars )
		{
			Dictionary<string, string> MergeVars = new Dictionary<string, string>();
			//
			foreach ( KeyValuePair<string, object> kv in merge_vars )
			{
				if ( kv.Key.ToLower().Contains( "groupings" ) )
				{
					int ix = -1;
					List<interestGroupings> igList = kv.Value as List<interestGroupings>;
					//
					foreach ( interestGroupings ig in igList )
					{
						ix++;
						string groups = "";
						if ( ig.groups.Count > 0 )
							groups = apiHelper.MakeStringFromList( ig.groups );
						if ( ig.id > 0 )
							MergeVars.Add( string.Format( "[groupings][{0}][{1}]", ix, "id" ), ig.id.ToString() ?? "" );
						if ( !string.IsNullOrEmpty( ig.name ) )
							MergeVars.Add( string.Format( "[groupings][{0}][{1}]", ix, "name" ), ig.name ?? "" );
						MergeVars.Add( string.Format( "[groupings][{0}][{1}]", ix, "groups" ), groups );
					}
				}
				else if ( kv.Value.GetType().Name.ToLower().Contains( "dictionary" ) )
				{
					foreach ( KeyValuePair<string, object> kvp in kv.Value as Dictionary<string, object> )
					{
						MergeVars.Add( string.Format( "[{0}][{1}]", kv.Key, kvp.Key ), kvp.Value.ToString() ?? "" );
					}
				}
				else if ( kv.Value.GetType().Name.ToLower().Contains( "datetime" ) )
				{
					DateTime dt = (DateTime)kv.Value;
					MergeVars.Add( string.Format( "[{0}]", kv.Key ), apiHelper.FormatApiDateParm( dt ) );
				}
				else
					MergeVars.Add( string.Format( "[{0}]", kv.Key ), kv.Value.ToString() ?? "" );
			}
			//
			return MergeVars;
		}

		// ---------------------------------------------------------------------------- GetXmlOutputError
		internal static Api_Error GetXmlOutputError( XElement xml )
		{
			// NOTE: api_BaseOutput allows for multiple errors in future, but MC only returns one for now...
			if ( xml.Element( "error" ) != null && xml.Element( "code" ) != null )
			//if ( xml.Elements( "error" ).Count() > 0 )
			{
				// -------- only 1 for now, so don't sweat the small stuff
				Api_Error aError = new Api_Error();
				aError.error = xml.Element( "error" ).Value ?? "";
				aError.code = xml.Element( "code" ).Value ?? "";
				// 
				return aError;
			}
			else
				return null;
		}

		#endregion
	}
}
